package com.shycloud.mido.common.api.vo;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import static java.util.stream.Collectors.toList;

/**
 * @author Xiaoxing Yu
 * @date 2020/12/10 下午4:02
 **/
public class IPageWrapper<T> implements Serializable {

	private static final long serialVersionUID = -9031745871532507434L;

	/**
	 * 查询数据列表
	 */
	private List<T> records = Collections.emptyList();
	/**
	 * 总数
	 */
	private long total = 0;
	/**
	 * 每页显示条数，默认 10
	 */
	private long size = 10;
	/**
	 * 当前页
	 */
	private long current = 1;

	/**
	 * 一共分了多少页
	 */
	private long pages = 0;
	/**
	 * SQL 排序 ASC 数组
	 */
	private String[] ascs;
	/**
	 * SQL 排序 DESC 数组
	 */
	private String[] descs;
	/**
	 * 自动优化 COUNT SQL
	 */
	private boolean optimizeCountSql = true;
	/**
	 * 是否进行 count 查询
	 */
	private boolean isSearchCount = true;

	private Integer incompleteNumber;

	public IPageWrapper() {
		// to do nothing
	}

	/**
	 * 分页构造函数
	 *
	 * @param current 当前页
	 * @param size    每页显示条数
	 */
	public IPageWrapper(long current, long size) {
		this(current, size, 0);
	}

	public IPageWrapper(long current, long size, long total) {
		this(current, size, total, true);
	}

	public IPageWrapper(long current, long size, boolean isSearchCount) {
		this(current, size, 0, isSearchCount);
	}

	public IPageWrapper(long current, long size, long total, boolean isSearchCount) {
		if (current > 1) {
			this.current = current;
		}
		this.size = size;
		this.total = total;
		this.isSearchCount = isSearchCount;
	}

	/**
	 * 是否存在上一页
	 *
	 * @return true / false
	 */
	public boolean hasPrevious() {
		return this.current > 1;
	}

	/**
	 * 是否存在下一页
	 *
	 * @return true / false
	 */
	public boolean hasNext() {
		return this.current < this.getPages();
	}

	public List<T> getRecords() {
		return this.records;
	}

	public IPageWrapper<T> setRecords(List<T> records) {
		this.records = records;
		return this;
	}

	public long getTotal() {
		return this.total;
	}

	public IPageWrapper<T> setTotal(long total) {
		this.total = total;
		return this;
	}

	public long getSize() {
		return this.size;
	}

	public IPageWrapper<T> setSize(long size) {
		this.size = size;
		return this;
	}

	public long getCurrent() {
		return this.current;
	}

	public IPageWrapper<T> setCurrent(long current) {
		this.current = current;
		return this;
	}

	public String[] ascs() {
		return ascs;
	}

	public IPageWrapper<T> setAscs(List<String> ascs) {
		if (CollectionUtils.isNotEmpty(ascs)) {
			this.ascs = ascs.toArray(new String[0]);
		}
		return this;
	}

	/**
	 * 升序
	 *
	 * @param ascs 多个升序字段
	 */
	public IPageWrapper<T> setAsc(String... ascs) {
		this.ascs = ascs;
		return this;
	}

	public String[] descs() {
		return descs;
	}

	public IPageWrapper<T> setDescs(List<String> descs) {
		if (CollectionUtils.isNotEmpty(descs)) {
			this.descs = descs.toArray(new String[0]);
		}
		return this;
	}

	public boolean optimizeCountSql() {
		return optimizeCountSql;
	}

	public boolean isSearchCount() {
		if (total < 0) {
			return false;
		}
		return isSearchCount;
	}

	public IPageWrapper<T> setSearchCount(boolean isSearchCount) {
		this.isSearchCount = isSearchCount;
		return this;
	}

	public IPageWrapper<T> setOptimizeCountSql(boolean optimizeCountSql) {
		this.optimizeCountSql = optimizeCountSql;
		return this;
	}

	/**
	 * KEY/VALUE 条件
	 *
	 * @return ignore
	 */
	Map<Object, Object> condition() {
		return null;
	}

	/**
	 * 计算当前分页偏移量
	 */
	long offset() {
		return getCurrent() > 0 ? (getCurrent() - 1) * getSize() : 0;
	}

//	/**
//	 * 当前分页总页数
//	 */
//	long getPages() {
//		if (getSize() == 0) {
//			return 0L;
//		}
//		long pages = getTotal() / getSize();
//		if (getTotal() % getSize() != 0) {
//			pages++;
//		}
//		return pages;
//	}

	public Long getPages() {
		return this.pages;
	}

	/**
	 * 内部什么也不干
	 * <p>只是为了 json 反序列化时不报错</p>
	 */
	public IPageWrapper<T> setPages(long pages) {
		// to do nothing
		this.pages = pages;
		return this;
	}

	/**
	 * IPage 的泛型转换
	 *
	 * @param mapper 转换函数
	 * @param <R>    转换后的泛型
	 * @return 转换泛型后的 IPage
	 */
	@SuppressWarnings("unchecked")
	<R> IPageWrapper<R> convert(Function<? super T, ? extends R> mapper) {
		List<R> collect = this.getRecords().stream().map(mapper).collect(toList());
		return ((IPageWrapper<R>) this).setRecords(collect);
	}

	public Integer getIncompleteNumber() {
		return incompleteNumber;
	}

	public void setIncompleteNumber(Integer incompleteNumber) {
		this.incompleteNumber = incompleteNumber;
	}

}
